import React, { PureComponent } from 'react'
import {
  Button, Form, Input, message, Modal, Radio, Select, Spin, Tooltip, TreeSelect, Col, Row,
} from 'antd'
import { history } from '@umijs/max'
import list2tree from 'list2tree'
import sqlFormatter from 'sql-formatter'
import styles from './index.less'
import { getHashParameterByName } from '@/utils/helper'
import {
  executeCreateTableSql,
  getCreateTableSql,
  getDirList,
  offlineDatabases,
  offlinePreviewData,
  offlineSchema,
  offlineTables,
} from './api'
import { CreateDiffEditor, ProTable } from '@/components'

const { Option } = Select
const { TextArea } = Input
const { Item } = Form

const getNavTreeDataFunc = list2tree({
  idKey: 'id',
  parentIdKey: 'pid',
  newKey: {
    key: 'id',
    value: 'id',
    title: 'dirName',
  },
})

class DataSource extends PureComponent {
  constructor(props) {
    super(props)
    this.state = {
      dirId: getHashParameterByName('dirId'),
      sourceDs: null,
      targetDs: null,
      targetTables: null,
      sourceTables: null,
      infoCase: 1,
      scripts: '',
      sourceDsId: '',
      sourceTable: '',
      previewData: {
        columns: [],
        data: [],
      },
      targetSchema: [],
      sourceSchema: [],
      spinning: false,
    }
    this.form = React.createRef()
    this.customEditorRef = React.createRef()
  }

  componentDidMount() {
    this.offlineDatabases(0)
    this.getDirList()
    this.form && this.form.current.setFieldsValue({
      dirId: this.state.dirId || 0,
    })
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.data !== this.props.data) {
      const data = nextProps.data
      if (!data.id) return
      this.form && this.form.current.setFieldsValue({
        taskName: data.taskName,
        sourceDsId: `${data.sourceDsId}_${data.sourceDsType}`,
        targetDsId: `${data.targetDsId}_${data.targetDsType}`,
        incFilter: data.incFilter,
        targetTable: data.targetTable,
        sourceTable: data.sourceTable,
        // dataReplaceRuleId: data.dataReplaceRuleId,
        // isTruncate: !!data.isTruncate,
        // errorNumLimit: data.errorNumLimit,
        dirId: data.dirId,
      })
      this.setState({
        sourceDsId: data.sourceDsId,
        targetDsId: data.targetDsId,
        targetDsType: data.targetDsType,
        sourceTable: data.sourceTable,
      })
      this.offlineSchema(0, data.sourceDsId, data.sourceDsType, data.sourceSchema)
      this.offlineDatabases(1, data.sourceDsId)
      this.offlineSchema(1, data.targetDsId, data.targetDsType, data.targetSchema)
    }
  }

  getDirList = () => {
    getDirList().then((res) => {
      this.setState({
        treeData: getNavTreeDataFunc(res.data || []),
      })
    }, (error) => {
    })
  }

  offlineDatabases = (direction, dsId) => {
    offlineDatabases({ direction, dsId }).then((res) => {
      if (res.status === 200) {
        if (direction) {
          this.setState({
            targetDs: res.data,
          })
        } else {
          this.setState({
            sourceDs: res.data,
          })
        }
      } else if (direction) {
        this.setState({
          targetDs: [],
        })
      } else {
        this.setState({
          sourceDs: [],
        })
      }
    })
  }

  offlineTables = (direction, dsId, schema) => {
    this.setState({
      spinning: true,
    })
    offlineTables({ direction, dsId, schema: schema || '' }).then((res) => {
      if (res.status === 200) {
        if (direction) {
          this.setState({
            targetTables: res.data,
          })
        } else {
          this.setState({
            sourceTables: res.data,
          })
        }
      } else if (direction) {
        this.setState({
          targetTables: [],
        })
      } else {
        this.setState({
          sourceTables: [],
        })
      }
      this.setState({
        spinning: false,
      })
    })
  }

  valuesChange = (value, allValues) => {
    const key = Object.keys(value)[0]
    if (key === 'sourceDsId') {
      if (!allValues.sourceDsId) return
      const arr = allValues.sourceDsId.split('_')
      this.form.current.setFieldsValue({
        sourceTable: null,
        sourceSchema: null,
      })
      this.setState({
        sourceDsId: arr[0],
        sourceSchema: [],
        sourceTables: [],
      }, () => {
        this.offlineSchema(0, arr[0], arr[1])
      })
      this.offlineDatabases(1, arr[0])
    } else if (key === 'targetDsId') {
      if (!allValues.targetDsId) return
      const arr = allValues.targetDsId.split('_')
      this.form.current.setFieldsValue({
        targetTable: null,
        targetSchema: null,
      })
      this.setState({
        targetDsId: arr[0],
        targetDsType: arr[1],
        targetSchema: [],
        targetTables: [],
        schema: '',
      }, () => {
        this.offlineSchema(1, arr[0], arr[1])
      })
    } else if (key === 'sourceTable') {
      this.setState({
        sourceTable: allValues.sourceTable,
      })
    } else if (key === 'sourceSchema') {
      this.form.current.setFieldsValue({
        sourceTable: null,
      })
      this.offlineTables(0, this.state.sourceDsId, allValues.sourceSchema)
    } else if (key === 'targetSchema') {
      this.form.current.setFieldsValue({
        targetTable: null,
      })
      this.setState({
        schema: allValues.targetSchema,
      })
      this.offlineTables(1, this.state.targetDsId, allValues.targetSchema)
    }
  }

  offlineSchema = (type, dsId, dsType, schema) => {
    this.setState({
      spinning: true,
    })
    offlineSchema({ dsId, dsType }).then((res) => {
      if (res.status === 200) {
        if (res.data && res.data.length) {
          if (type) {
            this.setState({
              targetSchema: res.data,
            }, () => {
              if (schema) {
                this.form.current.setFieldsValue({
                  targetSchema: schema,
                })
                this.offlineTables(type, dsId, schema)
              }
            })
          } else {
            this.setState({
              sourceSchema: res.data,
            }, () => {
              if (schema) {
                this.form.current.setFieldsValue({
                  sourceSchema: schema,
                })
                this.offlineTables(type, dsId, schema)
              }
            })
          }
        } else {
          this.offlineTables(type, dsId)
        }
      } else {
        message.error(res.msg)
      }
      this.setState({
        spinning: false,
      })
    })
  }

  // eslint-disable-next-line consistent-return
  offlinePreviewData = () => {
    const { sourceDsId, sourceTable } = this.state
    if (!sourceDsId || !sourceTable) return message.error('数据来源或数据表不能为空')
    offlinePreviewData({ dsId: sourceDsId, tableName: sourceTable }).then((res) => {
      this.setState({
        dataShows: true,
      })
      if (res.status === 200) {
        const data = []
        const columns = []
        res.data && res.data.fieldNameList
          && res.data.fieldNameList.map((name, i) => {
            columns.push({
              title: name,
              dataIndex: name,
              key: name,
              width: 100,
            })
          })
        res.data && res.data.dataList
          && res.data.dataList.map((arr, key) => {
            const dataObj = { key }
            res.data.fieldNameList
              && res.data.fieldNameList.map((name, i) => {
                dataObj[name] = arr[i]
              })
            data.push(dataObj)
          })
        this.setState({
          previewData: {
            columns,
            data,
          },
        })
      } else {
        message.warning(res.msg)
      }
    })
  }

  // eslint-disable-next-line consistent-return
  getCreateTableSql = () => {
    const {
      sourceDsId, sourceTable, targetDsId, schema, infoCase,
    } = this.state
    if (!sourceDsId || !sourceTable || !targetDsId) return message.error('数据来源、数据表或数据源目标不能为空')
    this.setState({
      loading: true,
    })
    getCreateTableSql({
      dsId: sourceDsId, tableName: sourceTable, targetDsId, schema: schema || '', infoCase,
    }).then((res) => {
      if (res.status === 200) {
        this.setState({
          scripts: res.data,
          isShows: true,
          loading: false,
        })
      } else {
        this.setState({
          loading: false,
        })
        message.error(res.msg)
      }
    })
  }

  /**
   * sql语句发生改变
   */
  valueChange = (scripts) => {
    this.setState({
      scripts,
    })
  };

  executeCreateTableSql = () => {
    const jsScript = this.customEditorRef?.current?.getEditorValue() || ''
    executeCreateTableSql({
      dsId: this.state.targetDsId,
      scripts: jsScript,
      }).then((res) => {
      if (res?.status === 200) {
        this.setState({
          isShows: false,
        })

        if (res?.data) {
          this.offlineTables(1, this.state.targetDsId, res.data.schema)
          this.form.current.setFieldsValue({
            targetTable: res.data?.tableName,
            targetSchema: res.data?.schema,
          })
        }
        message.success(res?.msg)
      } else {
        message.error(res?.msg)
      }
    })
  }

  onConfirm = () => {
    this.form.current.validateFields().then(values => {
      this.props.currentStepChange(1, {
        ...values,
        sourceDsId: values.sourceDsId.split('_')[0],
        sourceDsType: values.sourceDsId.split('_')[1],
        targetDsId: values.targetDsId.split('_')[0],
        targetDsType: values.targetDsId.split('_')[1],
        // isTruncate: values.isTruncate ? 1 : 0,
      })
    })
  }

  // tableExist = (i, dsId, tableName) => {
  //   tableExist({
  //     dsId,
  //     tableName,
  //   }).then((res) => {
  //     if (res.status === 200) {
  //       if (i) {
  //         this.setState({
  //           targetTableIs: res.data,
  //         })
  //       } else {
  //         this.setState({
  //           sourceTableIs: res.data,
  //         })
  //       }
  //     } else {
  //       message.error(res.msg)
  //     }
  //   })
  // }

  render() {
    const {
      sourceDs, targetDs, sourceTables, targetTables, scripts, loading, spinning,
      previewData, targetDsType, infoCase, shellEditorLoading,
      treeData, targetSchema, sourceSchema,
    } = this.state
    const values = this.form.current?.getFieldsValue(true)
    return (
      <div className={styles.data_source} style={{ ...this.props.style }}>
        <Spin spinning={spinning}>
          <Form
            className={styles.form}
            colon={false}
            labelCol={{ span: 4 }}
            wrapperCol={{ span: 20 }}
            onValuesChange={this.valuesChange}
            ref={this.form}
          >
            <Form.Item>
              <div className={styles.column}>基础设置</div>
            </Form.Item>
            <Form.Item
              label="任务名称"
              name="taskName"
              rules={[{ required: true, message: '请输入任务名称' }]}
            >
              <Input placeholder="请输入任务名称" />
            </Form.Item>
            <Form.Item
              label="目录"
              name="dirId"
              rules={[{ required: true, message: '请输入选择目录' }]}
            >
              <TreeSelect
                allowClear
                showSearch
                getPopupContainer={(triggerNode) => triggerNode.parentNode}
                // dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
                treeData={treeData}
                placeholder="请输入选择目录"
                treeDefaultExpandAll
                optionFilterProp="children"
                filterTreeNode={(input, treeNode) => treeNode.dirName.toLowerCase().indexOf(input.toLowerCase()) >= 0}
                fieldNames={{
                  label: 'dirName', value: 'id', children: 'children',
                }}
              />
            </Form.Item>
            <Form.Item>
              <div className={styles.column}>数据来源</div>
            </Form.Item>
            <Form.Item
              label="数据来源"
              name="sourceDsId"
              rules={[{ required: true, message: '请选择数据来源' }]}
            >
              <Select
                showSearch
                optionFilterProp="title"
                filterOption={(input, option) => option.title.toLowerCase().indexOf(input.toLowerCase()) >= 0}
                allowClear
                placeholder="请选择数据来源"
                getPopupContainer={(triggerNode) => triggerNode.parentNode}
              >
                {sourceDs && sourceDs.map((item) => (
                  <Option title={item.dsName} value={`${item.id}_${item.dsType}`} key={`${item.id}_${item.dsType}`}>
                    <div className={styles.source_name}>
                      {item.dsName}
                    </div>
                    <i
                      title={`${item.status ? '连接状态：正常' : '链接状态：失败'}`}
                      style={{ color: item.status ? '#43a047' : '#ef5350' }}
                      className={`iconfont ${item.status ? `icon-chenggong ${styles.chenggong}` : `icon-shibai1 ${styles.shibai}`}`}
                    />
                  </Option>
                ))}
              </Select>
            </Form.Item>
            {sourceSchema && sourceSchema.length ? (
              <Form.Item
                label="schema"
                name="sourceSchema"
                rules={[{ required: true, message: '请选择schema' }]}
              >
                <Select
                  showSearch
                  optionFilterProp="title"
                  filterOption={(input, option) => option.title.toLowerCase().indexOf(input.toLowerCase()) >= 0}
                  allowClear
                  placeholder="请选择schema"
                  getPopupContainer={(triggerNode) => triggerNode.parentNode}
                >
                  {sourceSchema && sourceSchema.map((value) => (
                    <Option title={value} value={value}>
                      {value}
                    </Option>
                  ))}
                </Select>
              </Form.Item>
            ) : null}
            <Form.Item
              label="来源表"
              name="sourceTable"
              rules={[{ required: true, message: '请选择来源表' }]}
            >
              {/* {sourceDsType === 'Sap' ? (
              <Input
                placeholder="请输入来源表"
                onBlur={(e) => {
                  this.tableExist(0, this.state.sourceDsId, e.target.value)
                }}
              />
            ) : (
              <Select
                allowClear
                placeholder="请选择来源表"
                showSearch
                filterOption={(input, option) => option.title.indexOf(input) >= 0}
              >
                {sourceTables && sourceTables.map((item) => <Option title={item.tableName} value={item.tableName} key={item.tableName}>{item.tableName}</Option>)}
              </Select>
            )} */}
              <Select
                allowClear
                placeholder="请选择来源表"
                showSearch
                optionFilterProp="title"
                filterOption={(input, option) => option.title.toLowerCase().indexOf(input.toLowerCase()) >= 0}
                getPopupContainer={(triggerNode) => triggerNode.parentNode}
              >
                {sourceTables && sourceTables.map((item) => <Option disabled={(values?.sourceDsId === values?.targetDsId) && (values?.targetTable === (item.schema ? `${item.schema}.${item.tableName}` : item.tableName))} title={item.schema ? `${item.schema}.${item.tableName}` : item.tableName} value={item.schema ? `${item.schema}.${item.tableName}` : item.tableName} key={item.schema ? `${item.schema}.${item.tableName}` : item.tableName}>{item.schema ? `${item.schema}.${item.tableName}` : item.tableName}</Option>)}
              </Select>
            </Form.Item>
            <div>
              <Form.Item
                label={
                  <span>
                    数据过滤
                    <Tooltip title={
                      <div>
                        <p>where 条件即针对源头数据筛选条件，根据指定的 column、table、where 条件拼接 SQL 进行数据抽取。利用 where 条件可进行全量同步和增量同步，具体说明如下：</p>
                        <p>1）全量同步：第一次做数据导入时通常为全量导入，可不用设置 where 条件。</p>
                        <p>{'2）增量同步：增量导入在实际业务场景中，往往会选择当天的数据进行同步，通常需要编写 where 条件语句，请先确认表中描述增量字段（时间戳）为哪一个。如tableA增量的字段为create_time，则填写create_time > 您需要的日期，如果需要日期动态变化，请参考帮助文档。'}</p>
                        <p>{'例如ID自增的增量同步：ID > ${to_db[select max(ID) from table_name]}'}</p>
                      </div>
                    }
                    >
                      <i className="iconfont icon-yiwentishi" />
                    </Tooltip>
                  </span>
                }
                name="incFilter"
                rules={[{ required: false, message: '请输入过滤条件' }]}
              >
                <TextArea
                  rows={4}
                  placeholder="请参考相关SQL语法填写where过滤语句（不要填写where关键字），该过滤语句通常用作增量同步。"
                />
              </Form.Item>
              <div
                onClick={() => {
                  this.offlinePreviewData()
                }}
                className={styles.data_see}
              >数据预览
              </div>
            </div>
            <Form.Item>
              <div className={styles.column}>数据目标</div>
            </Form.Item>
            <Form.Item
              label="数据目标"
              name="targetDsId"
              rules={[{ required: true, message: '请选择数据目标' }]}
            >
              <Select
                showSearch
                optionFilterProp="title"
                filterOption={(input, option) => option.title.toLowerCase().indexOf(input.toLowerCase()) >= 0}
                allowClear
                placeholder="请选择数据目标"
                getPopupContainer={(triggerNode) => triggerNode.parentNode}
              >
                {targetDs && targetDs.map((item) => (
                  <Option title={item.dsName} value={`${item.id}_${item.dsType}`} key={`${item.id}_${item.dsType}`}>
                    <div className={styles.source_name}>
                      {item.dsName}
                    </div>
                    <i
                      title={`${item.status ? '连接状态：正常' : '链接状态：失败'}`}
                      style={{ color: item.status ? '#43a047' : '#ef5350' }}
                      className={`iconfont ${item.status ? `icon-chenggong ${styles.chenggong}` : `icon-shibai1 ${styles.shibai}`}`}
                    />
                  </Option>
                ))}
              </Select>
            </Form.Item>
            {targetSchema && targetSchema.length ? (
              <Form.Item
                label="schema"
                name="targetSchema"
                rules={[{ required: true, message: '请选择schema' }]}
              >
                <Select
                  showSearch
                  optionFilterProp="title"
                  filterOption={(input, option) => option.title.toLowerCase().indexOf(input.toLowerCase()) >= 0}
                  allowClear
                  placeholder="请选择schema"
                  getPopupContainer={(triggerNode) => triggerNode.parentNode}
                >
                  {targetSchema && targetSchema.map((value) => (
                    <Option title={value} value={value}>
                      {value}
                    </Option>
                  ))}
                </Select>
              </Form.Item>
            ) : null}
            <div className={styles.target_table}>
              <Form.Item
                label="目标表"
                name="targetTable"
                rules={[{ required: true, message: '请选择目标表' }]}
              >
                {/* {targetDsType === 'Sap' ? (
                <Input
                  style={{ width: 'calc(100% - 1.2rem)' }}
                  placeholder="请输入目标表"
                  onBlur={(e) => {
                    this.tableExist(1, this.state.targetDsId, e.target.value)
                  }}
                />
              ) : (
                <Select
                  allowClear
                  placeholder="请选择目标表"
                  showSearch
                  filterOption={(input, option) => option.title.indexOf(input) >= 0}
                >
                  {targetTables && targetTables.map((item) => <Option title={item.tableName} value={item.tableName} key={item.tableName}>{item.tableName}</Option>)}
                </Select>
              )} */}
                <Select
                  allowClear
                  placeholder="请选择目标表"
                  optionFilterProp="title"
                  showSearch
                  filterOption={(input, option) => option.title.toLowerCase().indexOf(input.toLowerCase()) >= 0}
                  getPopupContainer={(triggerNode) => triggerNode.parentNode}
                >
                  {targetTables && targetTables.map((item) => <Option disabled={(values?.sourceDsId === values?.targetDsId) && (values?.sourceTable === (item.schema ? `${item.schema}.${item.tableName}` : item.tableName))} title={item.schema ? `${item.schema}.${item.tableName}` : item.tableName} value={item.schema ? `${item.schema}.${item.tableName}` : item.tableName} key={item.schema ? `${item.schema}.${item.tableName}` : item.tableName}>{item.schema ? `${item.schema}.${item.tableName}` : item.tableName}</Option>)}
                </Select>
              </Form.Item>
              <Button
                loading={loading}
                onClick={() => {
                  this.getCreateTableSql()
                }}
                className={styles.target_table_clear}
                style={{ float: 'right' }}
              >一键建表
              </Button>
            </div>
            {/* <Form.Item */}
            {/*  label=" " */}
            {/*  name="isTruncate" */}
            {/*  valuePropName="checked" */}
            {/* > */}
            {/*  <Checkbox>同步前清空历史数据</Checkbox> */}
            {/* </Form.Item> */}
            {/* <Form.Item */}
            {/*  label="写入模式" */}
            {/*  name="dataReplaceRuleId" */}
            {/*  rules={[{ required: true, message: '请选择写入模' }]} */}
            {/* > */}
            {/*  <Radio.Group> */}
            {/*    {targetDsType === 'Hive' ? <Radio value={1}>覆盖（Insert Overwrite）</Radio> : null} */}
            {/*    {targetDsType === 'Hive' ? <Radio value={2}>追加（Insert Into）</Radio> : null} */}
            {/*    {targetDsType !== 'Hive' ? <Radio value={5}>主键冲突，替换原有数据</Radio> : null} */}
            {/*    {targetDsType !== 'Hive' ? <Radio value={6}>主键冲突，丢弃新数据</Radio> : null} */}
            {/*  </Radio.Group> */}
            {/* </Form.Item> */}
            {/* <Form.Item */}
            {/*  className={styles.check_bar} */}
            {/*  label="脏数据限制" */}
            {/*  style={{ marginTop: '.1rem' }} */}
            {/*  initialValue={10} */}
            {/*  name="errorNumLimit" */}
            {/*  rules={[{ */}
            {/*    required: false, */}
            {/*    // eslint-disable-next-line prefer-regex-literals */}
            {/*    // pattern: new RegExp('/[0-9]/', ''), */}
            {/*    // message: '请选择脏数据限制', */}
            {/*  }]} */}
            {/* > */}
            {/*  <InputNumber min={0} addonBefore="单次同步失败记录数超过" addonAfter="条则任务结束" /> */}
            {/* </Form.Item> */}
          </Form>
          <div className={styles.edit_footer}>
            <Button onClick={() => { history.push('/dataIntegrate/offline/manager') }} className={styles.edit_btn}>取消</Button>
            <Button
              className={styles.edit_btn}
              type="primary"
              onClick={this.onConfirm}
            >下一步
            </Button>
          </div>
        </Spin>
        <Modal
          destroyOnClose
          title="一键建表"
          width="8.5rem"
          visible={this.state.isShows}
          confirmLoading={this.state.confirmLoading}
          onOk={() => {
            this.executeCreateTableSql()
          }}
          onCancel={() => {
            this.setState({
              isShows: false,
            })
          }}
        >
          <Spin spinning={loading}>
            <div className={styles.CreateDiff_Editor_Modal}>
              <Row gutter={100}>
                <Col span={12}>
                  <Radio.Group
                    style={{ paddingBottom: '.2rem' }}
                    onChange={(e) => {
                      this.setState({
                        infoCase: e.target.value,
                      }, () => {
                        this.getCreateTableSql()
                      })
                    }}
                    value={infoCase}
                  >
                    <Radio value={1}>原表保持一致</Radio>
                    <Radio value={2}>全部大写</Radio>
                    <Radio value={3}>全部小写</Radio>
                  </Radio.Group>
                </Col>
              </Row>
              <CreateDiffEditor
                restData={scripts && sqlFormatter.format(scripts) || ''}
                // restData={scripts || ''}
                // ref={(dev) => {
                //   this.shellEditorRef = dev
                // }}
                ref={this.customEditorRef}
                valueChange={this.valueChange}
                language="sql"
                editorId="data-target-editor"
              />

            </div>
          </Spin>
        </Modal>
        <Modal
          destroyOnClose
          title="数据预览"
          width="7rem"
          visible={this.state.dataShows}
          confirmLoading={this.state.confirmLoading}
          bodyStyle={{
            maxHeight: `${document.documentElement.clientHeight * 0.65}px`,
            overflowY: 'auto',
          }}
          onOk={() => {
            this.setState({
              dataShows: false,
            })
          }}
          onCancel={() => {
            this.setState({
              dataShows: false,
            })
          }}
          footer={false}
        >
          <div className={styles.CreateDiff_Editor_Modal}>
            <ProTable
              pagination={false}
              columns={previewData.columns}
              dataSource={previewData.data}
              scroll={{ x: 700 }}
              emptyText="暂无数据"
            />
          </div>
        </Modal>
      </div>
    )
  }
}

export default DataSource
